(function (
) {
    var Backbone,
        root = this,
        previousBackbone = root.Backbone,
        array = [],
        slice = array.slice;
    (Backbone =
    "undefined" != typeof exports
        ? exports
        : (root.Backbone = {
        })).VERSION =
    "1.1.0";
    var _ = root._;
    _ || "undefined" == typeof require || (_ = require(
        "underscore"
    )),
    (Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$),
    (Backbone.noConflict = function (
    ) {
        return (root.Backbone = previousBackbone), this;
    }),
    (Backbone.emulateHTTP = !1),
    (Backbone.emulateJSON = !1);
    var Events = (Backbone.Events = {
            on: function (
                name, callback, context
            ) {
                return eventsApi(
                    this,
                    "on",
                    name,
                    [callback, context,]
                ) && callback
                    ? (this._events || (this._events = {
                    }),
                    (this._events[name] || (this._events[name] = [])).push(
                        {
                            callback: callback,
                            context: context,
                            ctx: context || this,
                        }
                    ),
                    this)
                    : this;
            },
            once: function (
                name, callback, context
            ) {
                if (!eventsApi(
                    this,
                    "once",
                    name,
                    [callback, context,]
                ) || !callback)
                    return this;
                var self = this,
                    once = _.once(
                        function (
                        ) {
                            self.off(
                                name,
                                once
                            ), callback.apply(
                                this,
                                arguments
                            );
                        }
                    );
                return (once._callback = callback), this.on(
                    name,
                    once,
                    context
                );
            },
            off: function (
                name, callback, context
            ) {
                var retain, ev, events, names, i, l, j, k;
                if (!this._events || !eventsApi(
                    this,
                    "off",
                    name,
                    [callback, context,]
                ))
                    return this;
                if (!name && !callback && !context) return (this._events = {
                }), this;
                for (
                    i = 0, l = (names = name
                        ? [name,]
                        : _.keys(
                            this._events
                        )).length;
                    i < l;
                    i++
                )
                    if (((name = names[i]), (events = this._events[name]))) {
                        if (((this._events[name] = retain = []), callback || context))
                            for (j = 0, k = events.length; j < k; j++)
                                (ev = events[j]),
                                ((callback &&
                    callback !== ev.callback &&
                    callback !== ev.callback._callback) ||
                    (context && context !== ev.context)) &&
                    retain.push(
                        ev
                    );
                        retain.length || delete this._events[name];
                    }
                return this;
            },
            trigger: function (
                name
            ) {
                if (!this._events) return this;
                var args = slice.call(
                    arguments,
                    1
                );
                if (!eventsApi(
                    this,
                    "trigger",
                    name,
                    args
                )) return this;
                var events = this._events[name],
                    allEvents = this._events.all;
                return (
                    events && triggerEvents(
                        events,
                        args
                    ),
                    allEvents && triggerEvents(
                        allEvents,
                        arguments
                    ),
                    this
                );
            },
            stopListening: function (
                obj, name, callback
            ) {
                var listeningTo = this._listeningTo;
                if (!listeningTo) return this;
                var remove = !name && !callback;
                for (var id in (callback ||
          "object" != typeof name ||
          (callback = this),
                obj && ((listeningTo = {
                })[obj._listenId] = obj),
                listeningTo))
                    (obj = listeningTo[id]).off(
                        name,
                        callback,
                        this
                    ),
                    (remove || _.isEmpty(
                        obj._events
                    )) && delete this._listeningTo[id];
                return this;
            },
        }),
        eventSplitter = /\s+/,
        eventsApi = function (
            obj, action, name, rest
        ) {
            if (!name) return !0;
            if ("object" == typeof name) {
                for (var key in name)
                    obj[action].apply(
                        obj,
                        [key, name[key],].concat(
                            rest
                        )
                    );
                return !1;
            }
            if (eventSplitter.test(
                name
            )) {
                for (
                    var names = name.split(
                            eventSplitter
                        ), i = 0, l = names.length;
                    i < l;
                    i++
                )
                    obj[action].apply(
                        obj,
                        [names[i],].concat(
                            rest
                        )
                    );
                return !1;
            }
            return !0;
        },
        triggerEvents = function (
            events, args
        ) {
            var ev,
                i = -1,
                l = events.length,
                a1 = args[0],
                a2 = args[1],
                a3 = args[2];
            switch (args.length) {
            case 0:
                for (; ++i < l; ) (ev = events[i]).callback.call(
                    ev.ctx
                );
                return;
            case 1:
                for (; ++i < l; ) (ev = events[i]).callback.call(
                    ev.ctx,
                    a1
                );
                return;
            case 2:
                for (; ++i < l; ) (ev = events[i]).callback.call(
                    ev.ctx,
                    a1,
                    a2
                );
                return;
            case 3:
                for (; ++i < l; ) (ev = events[i]).callback.call(
                    ev.ctx,
                    a1,
                    a2,
                    a3
                );
                return;
            default:
                for (; ++i < l; ) (ev = events[i]).callback.apply(
                    ev.ctx,
                    args
                );
            }
        };
    _.each(
        {
            listenTo: "on",
            listenToOnce: "once",
        },
        function (
            implementation, method
        ) {
            Events[method] = function (
                obj, name, callback
            ) {
                return (
                    ((this._listeningTo || (this._listeningTo = {
                    }))[
                        obj._listenId || (obj._listenId = _.uniqueId(
                            "l"
                        ))
                    ] = obj),
                    callback || "object" != typeof name || (callback = this),
                    obj[implementation](
                        name,
                        callback,
                        this
                    ),
                    this
                );
            };
        },
    ),
    (Events.bind = Events.on),
    (Events.unbind = Events.off),
    _.extend(
        Backbone,
        Events
    );
    var Model = (Backbone.Model = function (
        attributes, options
    ) {
        var attrs = attributes || {
        };
        options || (options = {
        }),
        (this.cid = _.uniqueId(
            "c"
        )),
        (this.attributes = {
        }),
        options.collection && (this.collection = options.collection),
        options.parse && (attrs = this.parse(
            attrs,
            options
        ) || {
        }),
        (attrs = _.defaults(
            {
            },
            attrs,
            _.result(
                this,
                "defaults"
            )
        )),
        this.set(
            attrs,
            options
        ),
        (this.changed = {
        }),
        this.initialize.apply(
            this,
            arguments
        );
    });
    _.extend(
        Model.prototype,
        Events,
        {
            changed: null,
            validationError: null,
            idAttribute: "id",
            initialize: function (
            ) {},
            toJSON: function (
                options
            ) {
                return _.clone(
                    this.attributes
                );
            },
            sync: function (
            ) {
                return Backbone.sync.apply(
                    this,
                    arguments
                );
            },
            get: function (
                attr
            ) {
                return this.attributes[attr];
            },
            escape: function (
                attr
            ) {
                return _.escape(
                    this.get(
                        attr
                    )
                );
            },
            has: function (
                attr
            ) {
                return null != this.get(
                    attr
                );
            },
            set: function (
                key, val, options
            ) {
                var attr, attrs, unset, changes, silent, changing, prev, current;
                if (null == key) return this;
                if (
                    ("object" == typeof key
                        ? ((attrs = key), (options = val))
                        : ((attrs = {
                        })[key] = val),
                    options || (options = {
                    }),
                    !this._validate(
                        attrs,
                        options
                    ))
                )
                    return !1;
                for (attr in ((unset = options.unset),
                (silent = options.silent),
                (changes = []),
                (changing = this._changing),
                (this._changing = !0),
                changing ||
        ((this._previousAttributes = _.clone(
            this.attributes
        )),
        (this.changed = {
        })),
                (current = this.attributes),
                (prev = this._previousAttributes),
                this.idAttribute in attrs && (this.id = attrs[this.idAttribute]),
                attrs))
                    (val = attrs[attr]),
                    _.isEqual(
                        current[attr],
                        val
                    ) || changes.push(
                        attr
                    ),
                    _.isEqual(
                        prev[attr],
                        val
                    )
                        ? delete this.changed[attr]
                        : (this.changed[attr] = val),
                    unset ? delete current[attr] : (current[attr] = val);
                if (!silent) {
                    changes.length && (this._pending = !0);
                    for (var i = 0, l = changes.length; i < l; i++)
                        this.trigger(
                            "change:" + changes[i],
                            this,
                            current[changes[i]],
                            options,
                        );
                }
                if (changing) return this;
                if (!silent)
                    for (; this._pending; )
                        (this._pending = !1), this.trigger(
                            "change",
                            this,
                            options
                        );
                return (this._pending = !1), (this._changing = !1), this;
            },
            unset: function (
                attr, options
            ) {
                return this.set(
                    attr,
                    void 0,
                    _.extend(
                        {
                        },
                        options,
                        {
                            unset: !0,
                        }
                    )
                );
            },
            clear: function (
                options
            ) {
                var attrs = {
                };
                for (var key in this.attributes) attrs[key] = void 0;
                return this.set(
                    attrs,
                    _.extend(
                        {
                        },
                        options,
                        {
                            unset: !0,
                        }
                    )
                );
            },
            hasChanged: function (
                attr
            ) {
                return null == attr
                    ? !_.isEmpty(
                        this.changed
                    )
                    : _.has(
                        this.changed,
                        attr
                    );
            },
            changedAttributes: function (
                diff
            ) {
                if (!diff) return !!this.hasChanged(
                ) && _.clone(
                    this.changed
                );
                var val,
                    changed = !1,
                    old = this._changing ? this._previousAttributes : this.attributes;
                for (var attr in diff)
                    _.isEqual(
                        old[attr], (
                            val = diff[attr])
                    ) ||
          ((changed || (changed = {
          }))[attr] = val);
                return changed;
            },
            previous: function (
                attr
            ) {
                return null != attr && this._previousAttributes
                    ? this._previousAttributes[attr]
                    : null;
            },
            previousAttributes: function (
            ) {
                return _.clone(
                    this._previousAttributes
                );
            },
            fetch: function (
                options
            ) {
                void 0 === (options = options
                    ? _.clone(
                        options
                    )
                    : {
                    }).parse &&
        (options.parse = !0);
                var model = this,
                    success = options.success;
                return (
                    (options.success = function (
                        resp
                    ) {
                        if (!model.set(
                            model.parse(
                                resp,
                                options
                            ),
                            options
                        )) return !1;
                        success && success(
                            model,
                            resp,
                            options
                        ),
                        model.trigger(
                            "sync",
                            model,
                            resp,
                            options
                        );
                    }),
                    wrapError(
                        this,
                        options
                    ),
                    this.sync(
                        "read",
                        this,
                        options
                    )
                );
            },
            save: function (
                key, val, options
            ) {
                var attrs,
                    method,
                    xhr,
                    attributes = this.attributes;
                if (
                    (null == key || "object" == typeof key
                        ? ((attrs = key), (options = val))
                        : ((attrs = {
                        })[key] = val),
                    (options = _.extend(
                        {
                            validate: !0,
                        },
                        options
                    )),
                    attrs && !options.wait)
                ) {
                    if (!this.set(
                        attrs,
                        options
                    )) return !1;
                } else if (!this._validate(
                    attrs,
                    options
                )) return !1;
                attrs &&
        options.wait &&
        (this.attributes = _.extend(
            {
            },
            attributes,
            attrs
        )),
                void 0 === options.parse && (options.parse = !0);
                var model = this,
                    success = options.success;
                return (
                    (options.success = function (
                        resp
                    ) {
                        model.attributes = attributes;
                        var serverAttrs = model.parse(
                            resp,
                            options
                        );
                        if (
                            (options.wait && (serverAttrs = _.extend(
                                attrs || {
                                },
                                serverAttrs
                            )),
                            _.isObject(
                                serverAttrs
                            ) && !model.set(
                                serverAttrs,
                                options
                            ))
                        )
                            return !1;
                        success && success(
                            model,
                            resp,
                            options
                        ),
                        model.trigger(
                            "sync",
                            model,
                            resp,
                            options
                        );
                    }),
                    wrapError(
                        this,
                        options
                    ),
                    "patch" ===
          (method = this.isNew(
          )
              ? "create"
              : options.patch
                  ? "patch"
                  : "update") && (options.attrs = attrs),
                    (xhr = this.sync(
                        method,
                        this,
                        options
                    )),
                    attrs && options.wait && (this.attributes = attributes),
                    xhr
                );
            },
            destroy: function (
                options
            ) {
                options = options
                    ? _.clone(
                        options
                    )
                    : {
                    };
                var model = this,
                    success = options.success,
                    destroy = function (
                    ) {
                        model.trigger(
                            "destroy",
                            model,
                            model.collection,
                            options
                        );
                    };
                if (
                    ((options.success = function (
                        resp
                    ) {
                        (options.wait || model.isNew(
                        )) && destroy(
                        ),
                        success && success(
                            model,
                            resp,
                            options
                        ),
                        model.isNew(
                        ) || model.trigger(
                            "sync",
                            model,
                            resp,
                            options
                        );
                    }),
                    this.isNew(
                    ))
                )
                    return options.success(
                    ), !1;
                wrapError(
                    this,
                    options
                );
                var xhr = this.sync(
                    "delete",
                    this,
                    options
                );
                return options.wait || destroy(
                ), xhr;
            },
            url: function (
            ) {
                var base =
        _.result(
            this,
            "urlRoot"
        ) ||
        _.result(
            this.collection,
            "url"
        ) ||
        urlError(
        );
                return this.isNew(
                )
                    ? base
                    : base +
            ("/" === base.charAt(
                base.length - 1
            )
                ? ""
                : "/") +
            encodeURIComponent(
                this.id
            );
            },
            parse: function (
                resp, options
            ) {
                return resp;
            },
            clone: function (
            ) {
                return new this.constructor(
                    this.attributes
                );
            },
            isNew: function (
            ) {
                return null == this.id;
            },
            isValid: function (
                options
            ) {
                return this._validate(
                    {
                    },
                    _.extend(
                        options || {
                        },
                        {
                            validate: !0,
                        }
                    )
                );
            },
            _validate: function (
                attrs, options
            ) {
                if (!options.validate || !this.validate) return !0;
                attrs = _.extend(
                    {
                    },
                    this.attributes,
                    attrs
                );
                var error = (this.validationError =
        this.validate(
            attrs,
            options
        ) || null);
                return (
                    !error ||
        (this.trigger(
            "invalid",
            this,
            error,
            _.extend(
                options,
                {
                    validationError: error,
                }
            ),
        ),
        !1)
                );
            },
        }
    );
    _.each(
        ["keys", "values", "pairs", "invert", "pick", "omit",],
        function (
            method
        ) {
            Model.prototype[method] = function (
            ) {
                var args = slice.call(
                    arguments
                );
                return args.unshift(
                    this.attributes
                ), _[method].apply(
                    _,
                    args
                );
            };
        },
    );
    var Collection = (Backbone.Collection = function (
            models, options
        ) {
            options || (options = {
            }),
            options.model && (this.model = options.model),
            void 0 !== options.comparator && (this.comparator = options.comparator),
            this._reset(
            ),
            this.initialize.apply(
                this,
                arguments
            ),
            models && this.reset(
                models,
                _.extend(
                    {
                        silent: !0,
                    },
                    options
                )
            );
        }),
        setOptions = {
            add: !0,
            remove: !0,
            merge: !0,
        },
        addOptions = {
            add: !0,
            remove: !1,
        };
    _.extend(
        Collection.prototype,
        Events,
        {
            model: Model,
            initialize: function (
            ) {},
            toJSON: function (
                options
            ) {
                return this.map(
                    function (
                        model
                    ) {
                        return model.toJSON(
                            options
                        );
                    }
                );
            },
            sync: function (
            ) {
                return Backbone.sync.apply(
                    this,
                    arguments
                );
            },
            add: function (
                models, options
            ) {
                return this.set(
                    models,
                    _.extend(
                        {
                            merge: !1,
                        },
                        options,
                        addOptions
                    )
                );
            },
            remove: function (
                models, options
            ) {
                var i,
                    l,
                    index,
                    model,
                    singular = !_.isArray(
                        models
                    );
                for (
                    options || (options = {
                    }),
                    i = 0,
                    l = (models = singular
                        ? [models,]
                        : _.clone(
                            models
                        )).length;
                    i < l;
                    i++
                )
                    (model = models[i] = this.get(
                        models[i]
                    )) &&
          (delete this._byId[model.id],
          delete this._byId[model.cid],
          (index = this.indexOf(
              model
          )),
          this.models.splice(
              index,
              1
          ),
          this.length--,
          options.silent ||
            ((options.index = index),
            model.trigger(
                "remove",
                model,
                this,
                options
            )),
          this._removeReference(
              model
          ));
                return singular ? models[0] : models;
            },
            set: function (
                models, options
            ) {
                (options = _.defaults(
                    {
                    },
                    options,
                    setOptions
                )).parse &&
        (models = this.parse(
            models,
            options
        ));
                var i,
                    l,
                    id,
                    model,
                    attrs,
                    existing,
                    sort,
                    singular = !_.isArray(
                        models
                    );
                models = singular
                    ? (models ? [models,] : [])
                    : _.clone(
                        models
                    );
                var at = options.at,
                    targetModel = this.model,
                    sortable = this.comparator && null == at && !1 !== options.sort,
                    sortAttr = _.isString(
                        this.comparator
                    )
                        ? this.comparator
                        : null,
                    toAdd = [],
                    toRemove = [],
                    modelMap = {
                    },
                    add = options.add,
                    merge = options.merge,
                    remove = options.remove,
                    order = !(sortable || !add || !remove) && [];
                for (i = 0, l = models.length; i < l; i++) {
                    if (
                        ((id =
            (attrs = models[i]) instanceof Model
                ? (model = attrs)
                : attrs[targetModel.prototype.idAttribute]),
                        (existing = this.get(
                            id
                        )))
                    )
                        remove && (modelMap[existing.cid] = !0),
                        merge &&
              ((attrs = attrs === model ? model.attributes : attrs),
              options.parse && (attrs = existing.parse(
                  attrs,
                  options
              )),
              existing.set(
                  attrs,
                  options
              ),
              sortable &&
                !sort &&
                existing.hasChanged(
                    sortAttr
                ) &&
                (sort = !0)),
                        (models[i] = existing);
                    else if (add) {
                        if (!(model = models[i] = this._prepareModel(
                            attrs,
                            options
                        )))
                            continue;
                        toAdd.push(
                            model
                        ),
                        model.on(
                            "all",
                            this._onModelEvent,
                            this
                        ),
                        (this._byId[model.cid] = model),
                        null != model.id && (this._byId[model.id] = model);
                    }
                    order && order.push(
                        existing || model
                    );
                }
                if (remove) {
                    for (i = 0, l = this.length; i < l; ++i)
                        modelMap[(model = this.models[i]).cid] || toRemove.push(
                            model
                        );
                    toRemove.length && this.remove(
                        toRemove,
                        options
                    );
                }
                if (toAdd.length || (order && order.length))
                    if (
                        (sortable && (sort = !0), (this.length += toAdd.length), null != at)
                    )
                        for (i = 0, l = toAdd.length; i < l; i++)
                            this.models.splice(
                                at + i,
                                0,
                                toAdd[i]
                            );
                    else {
                        order && (this.models.length = 0);
                        var orderedModels = order || toAdd;
                        for (i = 0, l = orderedModels.length; i < l; i++)
                            this.models.push(
                                orderedModels[i]
                            );
                    }
                if ((sort && this.sort(
                    {
                        silent: !0,
                    }
                ), !options.silent)) {
                    for (i = 0, l = toAdd.length; i < l; i++)
                        (model = toAdd[i]).trigger(
                            "add",
                            model,
                            this,
                            options
                        );
                    (sort || (order && order.length)) &&
          this.trigger(
              "sort",
              this,
              options
          );
                }
                return singular ? models[0] : models;
            },
            reset: function (
                models, options
            ) {
                options || (options = {
                });
                for (var i = 0, l = this.models.length; i < l; i++)
                    this._removeReference(
                        this.models[i]
                    );
                return (
                    (options.previousModels = this.models),
                    this._reset(
                    ),
                    (models = this.add(
                        models,
                        _.extend(
                            {
                                silent: !0,
                            },
                            options
                        )
                    )),
                    options.silent || this.trigger(
                        "reset",
                        this,
                        options
                    ),
                    models
                );
            },
            push: function (
                model, options
            ) {
                return this.add(
                    model,
                    _.extend(
                        {
                            at: this.length,
                        },
                        options
                    )
                );
            },
            pop: function (
                options
            ) {
                var model = this.at(
                    this.length - 1
                );
                return this.remove(
                    model,
                    options
                ), model;
            },
            unshift: function (
                model, options
            ) {
                return this.add(
                    model,
                    _.extend(
                        {
                            at: 0,
                        },
                        options
                    )
                );
            },
            shift: function (
                options
            ) {
                var model = this.at(
                    0
                );
                return this.remove(
                    model,
                    options
                ), model;
            },
            slice: function (
            ) {
                return slice.apply(
                    this.models,
                    arguments
                );
            },
            get: function (
                obj
            ) {
                if (null != obj)
                    return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj];
            },
            at: function (
                index
            ) {
                return this.models[index];
            },
            where: function (
                attrs, first
            ) {
                return _.isEmpty(
                    attrs
                )
                    ? first
                        ? void 0
                        : []
                    : this[first ? "find" : "filter"](
                        function (
                            model
                        ) {
                            for (var key in attrs) if (attrs[key] !== model.get(
                                key
                            )) return !1;
                            return !0;
                        }
                    );
            },
            findWhere: function (
                attrs
            ) {
                return this.where(
                    attrs,
                    !0
                );
            },
            sort: function (
                options
            ) {
                if (!this.comparator)
                    throw new Error(
                        "Cannot sort a set without a comparator"
                    );
                return (
                    options || (options = {
                    }),
                    _.isString(
                        this.comparator
                    ) || 1 === this.comparator.length
                        ? (this.models = this.sortBy(
                            this.comparator,
                            this
                        ))
                        : this.models.sort(
                            _.bind(
                                this.comparator,
                                this
                            )
                        ),
                    options.silent || this.trigger(
                        "sort",
                        this,
                        options
                    ),
                    this
                );
            },
            pluck: function (
                attr
            ) {
                return _.invoke(
                    this.models,
                    "get",
                    attr
                );
            },
            fetch: function (
                options
            ) {
                void 0 === (options = options
                    ? _.clone(
                        options
                    )
                    : {
                    }).parse &&
        (options.parse = !0);
                var success = options.success,
                    collection = this;
                return (
                    (options.success = function (
                        resp
                    ) {
                        var method = options.reset ? "reset" : "set";
                        collection[method](
                            resp,
                            options
                        ),
                        success && success(
                            collection,
                            resp,
                            options
                        ),
                        collection.trigger(
                            "sync",
                            collection,
                            resp,
                            options
                        );
                    }),
                    wrapError(
                        this,
                        options
                    ),
                    this.sync(
                        "read",
                        this,
                        options
                    )
                );
            },
            create: function (
                model, options
            ) {
                if (
                    ((options = options
                        ? _.clone(
                            options
                        )
                        : {
                        }),
                    !(model = this._prepareModel(
                        model,
                        options
                    )))
                )
                    return !1;
                options.wait || this.add(
                    model,
                    options
                );
                var collection = this,
                    success = options.success;
                return (
                    (options.success = function (
                        model, resp, options
                    ) {
                        options.wait && collection.add(
                            model,
                            options
                        ),
                        success && success(
                            model,
                            resp,
                            options
                        );
                    }),
                    model.save(
                        null,
                        options
                    ),
                    model
                );
            },
            parse: function (
                resp, options
            ) {
                return resp;
            },
            clone: function (
            ) {
                return new this.constructor(
                    this.models
                );
            },
            _reset: function (
            ) {
                (this.length = 0), (this.models = []), (this._byId = {
                });
            },
            _prepareModel: function (
                attrs, options
            ) {
                if (attrs instanceof Model)
                    return attrs.collection || (attrs.collection = this), attrs;
                (options = options
                    ? _.clone(
                        options
                    )
                    : {
                    }).collection = this;
                var model = new this.model(
                    attrs,
                    options
                );
                return model.validationError
                    ? (this.trigger(
                        "invalid",
                        this,
                        model.validationError,
                        options
                    ), !1)
                    : model;
            },
            _removeReference: function (
                model
            ) {
                this === model.collection && delete model.collection,
                model.off(
                    "all",
                    this._onModelEvent,
                    this
                );
            },
            _onModelEvent: function (
                event, model, collection, options
            ) {
                (("add" !== event && "remove" !== event) || collection === this) &&
        ("destroy" === event && this.remove(
            model,
            options
        ),
        model &&
          event === "change:" + model.idAttribute &&
          (delete this._byId[model.previous(
              model.idAttribute
          )],
          null != model.id && (this._byId[model.id] = model)),
        this.trigger.apply(
            this,
            arguments
        ));
            },
        }
    );
    _.each(
        [
            "forEach",
            "each",
            "map",
            "collect",
            "reduce",
            "foldl",
            "inject",
            "reduceRight",
            "foldr",
            "find",
            "detect",
            "filter",
            "select",
            "reject",
            "every",
            "all",
            "some",
            "any",
            "include",
            "contains",
            "invoke",
            "max",
            "min",
            "toArray",
            "size",
            "first",
            "head",
            "take",
            "initial",
            "rest",
            "tail",
            "drop",
            "last",
            "without",
            "difference",
            "indexOf",
            "shuffle",
            "lastIndexOf",
            "isEmpty",
            "chain",
        ],
        function (
            method
        ) {
            Collection.prototype[method] = function (
            ) {
                var args = slice.call(
                    arguments
                );
                return args.unshift(
                    this.models
                ), _[method].apply(
                    _,
                    args
                );
            };
        },
    );
    _.each(
        ["groupBy", "countBy", "sortBy",],
        function (
            method
        ) {
            Collection.prototype[method] = function (
                value, context
            ) {
                var iterator = _.isFunction(
                    value
                )
                    ? value
                    : function (
                        model
                    ) {
                        return model.get(
                            value
                        );
                    };
                return _[method](
                    this.models,
                    iterator,
                    context
                );
            };
        }
    );
    var View = (Backbone.View = function (
            options
        ) {
            (this.cid = _.uniqueId(
                "view"
            )),
            options || (options = {
            }),
            _.extend(
                this,
                _.pick(
                    options,
                    viewOptions
                )
            ),
            this._ensureElement(
            ),
            this.initialize.apply(
                this,
                arguments
            ),
            this.delegateEvents(
            );
        }),
        delegateEventSplitter = /^(\S+)\s*(.*)$/,
        viewOptions = [
            "model",
            "collection",
            "el",
            "id",
            "attributes",
            "className",
            "tagName",
            "events",
        ];
    _.extend(
        View.prototype,
        Events,
        {
            tagName: "div",
            $: function (
                selector
            ) {
                return this.$el.find(
                    selector
                );
            },
            initialize: function (
            ) {},
            render: function (
            ) {
                return this;
            },
            remove: function (
            ) {
                return this.$el.remove(
                ), this.stopListening(
                ), this;
            },
            setElement: function (
                element, delegate
            ) {
                return (
                    this.$el && this.undelegateEvents(
                    ),
                    (this.$el =
          element instanceof Backbone.$
              ? element
              : Backbone.$(
                  element
              )),
                    (this.el = this.$el[0]),
                    !1 !== delegate && this.delegateEvents(
                    ),
                    this
                );
            },
            delegateEvents: function (
                events
            ) {
                if (!events && !(events = _.result(
                    this,
                    "events"
                ))) return this;
                for (var key in (this.undelegateEvents(
                ), events)) {
                    var method = events[key];
                    if ((_.isFunction(
                        method
                    ) || (method = this[events[key]]), method)) {
                        var match = key.match(
                                delegateEventSplitter
                            ),
                            eventName = match[1],
                            selector = match[2];
                        (method = _.bind(
                            method,
                            this
                        )),
                        (eventName += ".delegateEvents" + this.cid),
                        "" === selector
                            ? this.$el.on(
                                eventName,
                                method
                            )
                            : this.$el.on(
                                eventName,
                                selector,
                                method
                            );
                    }
                }
                return this;
            },
            undelegateEvents: function (
            ) {
                return this.$el.off(
                    ".delegateEvents" + this.cid
                ), this;
            },
            _ensureElement: function (
            ) {
                if (this.el) this.setElement(
                    _.result(
                        this,
                        "el"
                    ),
                    !1
                );
                else {
                    var attrs = _.extend(
                        {
                        },
                        _.result(
                            this,
                            "attributes"
                        )
                    );
                    this.id && (attrs.id = _.result(
                        this,
                        "id"
                    )),
                    this.className && (attrs.class = _.result(
                        this,
                        "className"
                    ));
                    var $el = Backbone.$(
                        "<" + _.result(
                            this,
                            "tagName"
                        ) + ">"
                    ).attr(
                        attrs
                    );
                    this.setElement(
                        $el,
                        !1
                    );
                }
            },
        }
    ),
    (Backbone.sync = function (
        method, model, options
    ) {
        var type = methodMap[method];
        _.defaults(
            options || (options = {
            }),
            {
                emulateHTTP: Backbone.emulateHTTP,
                emulateJSON: Backbone.emulateJSON,
            }
        );
        var params = {
            type: type,
            dataType: "json",
        };
        if (
            (options.url || (params.url = _.result(
                model,
                "url"
            ) || urlError(
            )),
            null != options.data ||
          !model ||
          ("create" !== method && "update" !== method && "patch" !== method) ||
          ((params.contentType = "application/json"),
          (params.data = JSON.stringify(
              options.attrs || model.toJSON(
                  options
              ),
          ))),
            options.emulateJSON &&
          ((params.contentType = "application/x-www-form-urlencoded"),
          (params.data = params.data
              ? {
                  model: params.data,
              }
              : {
              })),
            options.emulateHTTP &&
          ("PUT" === type || "DELETE" === type || "PATCH" === type))
        ) {
            (params.type = "POST"),
            options.emulateJSON && (params.data._method = type);
            var beforeSend = options.beforeSend;
            options.beforeSend = function (
                xhr
            ) {
                if (
                    (xhr.setRequestHeader(
                        "X-HTTP-Method-Override",
                        type
                    ), beforeSend)
                )
                    return beforeSend.apply(
                        this,
                        arguments
                    );
            };
        }
        "GET" === params.type || options.emulateJSON || (params.processData = !1),
        "PATCH" === params.type &&
          noXhrPatch &&
          (params.xhr = function (
          ) {
              return new ActiveXObject(
                  "Microsoft.XMLHTTP"
              );
          });
        var xhr = (options.xhr = Backbone.ajax(
            _.extend(
                params,
                options
            )
        ));
        return model.trigger(
            "request",
            model,
            xhr,
            options
        ), xhr;
    });
    var noXhrPatch = !(
            "undefined" == typeof window ||
      !window.ActiveXObject ||
      (window.XMLHttpRequest && new XMLHttpRequest(
      ).dispatchEvent)
        ),
        methodMap = {
            create: "POST",
            update: "PUT",
            patch: "PATCH",
            delete: "DELETE",
            read: "GET",
        };
    Backbone.ajax = function (
    ) {
        return Backbone.$.ajax.apply(
            Backbone.$,
            arguments
        );
    };
    var Router = (Backbone.Router = function (
            options
        ) {
            options || (options = {
            }),
            options.routes && (this.routes = options.routes),
            this._bindRoutes(
            ),
            this.initialize.apply(
                this,
                arguments
            );
        }),
        optionalParam = /\((.*?)\)/g,
        namedParam = /(\(\?)?:\w+/g,
        splatParam = /\*\w+/g,
        escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
    _.extend(
        Router.prototype,
        Events,
        {
            initialize: function (
            ) {},
            route: function (
                route, name, callback
            ) {
                _.isRegExp(
                    route
                ) || (route = this._routeToRegExp(
                    route
                )),
                _.isFunction(
                    name
                ) && ((callback = name), (name = "")),
                callback || (callback = this[name]);
                var router = this;
                return (
                    Backbone.history.route(
                        route,
                        function (
                            fragment
                        ) {
                            var args = router._extractParameters(
                                route,
                                fragment
                            );
                            callback && callback.apply(
                                router,
                                args
                            ),
                            router.trigger.apply(
                                router,
                                ["route:" + name,].concat(
                                    args
                                )
                            ),
                            router.trigger(
                                "route",
                                name,
                                args
                            ),
                            Backbone.history.trigger(
                                "route",
                                router,
                                name,
                                args
                            );
                        }
                    ),
                    this
                );
            },
            navigate: function (
                fragment, options
            ) {
                return Backbone.history.navigate(
                    fragment,
                    options
                ), this;
            },
            _bindRoutes: function (
            ) {
                if (this.routes) {
                    this.routes = _.result(
                        this,
                        "routes"
                    );
                    for (
                        var route, routes = _.keys(
                            this.routes
                        );
                        null != (route = routes.pop(
                        ));

                    )
                        this.route(
                            route,
                            this.routes[route]
                        );
                }
            },
            _routeToRegExp: function (
                route
            ) {
                return (
                    (route = route
                        .replace(
                            escapeRegExp,
                            "\\$&"
                        )
                        .replace(
                            optionalParam,
                            "(?:$1)?"
                        )
                        .replace(
                            namedParam,
                            function (
                                match, optional
                            ) {
                                return optional ? match : "([^/]+)";
                            }
                        )
                        .replace(
                            splatParam,
                            "(.*?)"
                        )),
                    new RegExp(
                        "^" + route + "$"
                    )
                );
            },
            _extractParameters: function (
                route, fragment
            ) {
                var params = route.exec(
                    fragment
                ).slice(
                    1
                );
                return _.map(
                    params,
                    function (
                        param
                    ) {
                        return param
                            ? decodeURIComponent(
                                param
                            )
                            : null;
                    }
                );
            },
        }
    );
    var History = (Backbone.History = function (
        ) {
            (this.handlers = []),
            _.bindAll(
                this,
                "checkUrl"
            ),
            "undefined" != typeof window &&
          ((this.location = window.location), (this.history = window.history));
        }),
        routeStripper = /^[#\/]|\s+$/g,
        rootStripper = /^\/+|\/+$/g,
        isExplorer = /msie [\w.]+/,
        trailingSlash = /\/$/,
        pathStripper = /[?#].*$/;
    (History.started = !1),
    _.extend(
        History.prototype,
        Events,
        {
            interval: 50,
            getHash: function (
                window
            ) {
                var match = (window || this).location.href.match(
                    /#(.*)$/
                );
                return match ? match[1] : "";
            },
            getFragment: function (
                fragment, forcePushState
            ) {
                if (null == fragment)
                    if (this._hasPushState || !this._wantsHashChange || forcePushState) {
                        fragment = this.location.pathname;
                        var root = this.root.replace(
                            trailingSlash,
                            ""
                        );
                        fragment.indexOf(
                            root
                        ) || (fragment = fragment.slice(
                            root.length
                        ));
                    } else fragment = this.getHash(
                    );
                return fragment.replace(
                    routeStripper,
                    ""
                );
            },
            start: function (
                options
            ) {
                if (History.started)
                    throw new Error(
                        "Backbone.history has already been started"
                    );
                (History.started = !0),
                (this.options = _.extend(
                    {
                        root: "/",
                    },
                    this.options,
                    options
                )),
                (this.root = this.options.root),
                (this._wantsHashChange = !1 !== this.options.hashChange),
                (this._wantsPushState = !!this.options.pushState),
                (this._hasPushState = !!(
                    this.options.pushState &&
            this.history &&
            this.history.pushState
                ));
                var fragment = this.getFragment(
                    ),
                    docMode = document.documentMode,
                    oldIE =
            isExplorer.exec(
                navigator.userAgent.toLowerCase(
                )
            ) &&
            (!docMode || docMode <= 7);
                (this.root = ("/" + this.root + "/").replace(
                    rootStripper,
                    "/"
                )),
                oldIE &&
            this._wantsHashChange &&
            ((this.iframe = Backbone.$(
                '<iframe src="javascript:0" tabindex="-1" />',
            )
                .hide(
                )
                .appendTo(
                    "body"
                )[0].contentWindow),
            this.navigate(
                fragment
            )),
                this._hasPushState
                    ? Backbone.$(
                        window
                    ).on(
                        "popstate",
                        this.checkUrl
                    )
                    : this._wantsHashChange && "onhashchange" in window && !oldIE
                        ? Backbone.$(
                            window
                        ).on(
                            "hashchange",
                            this.checkUrl
                        )
                        : this._wantsHashChange &&
              (this._checkUrlInterval = setInterval(
                  this.checkUrl,
                  this.interval,
              )),
                (this.fragment = fragment);
                var loc = this.location,
                    atRoot = loc.pathname.replace(
                        /[^\/]$/,
                        "$&/"
                    ) === this.root;
                if (this._wantsHashChange && this._wantsPushState) {
                    if (!this._hasPushState && !atRoot)
                        return (
                            (this.fragment = this.getFragment(
                                null,
                                !0
                            )),
                            this.location.replace(
                                this.root + this.location.search + "#" + this.fragment,
                            ),
                            !0
                        );
                    this._hasPushState &&
            atRoot &&
            loc.hash &&
            ((this.fragment = this.getHash(
            ).replace(
                routeStripper,
                ""
            )),
            this.history.replaceState(
                {
                },
                document.title,
                this.root + this.fragment + loc.search,
            ));
                }
                if (!this.options.silent) return this.loadUrl(
                );
            },
            stop: function (
            ) {
                Backbone.$(
                    window
                )
                    .off(
                        "popstate",
                        this.checkUrl
                    )
                    .off(
                        "hashchange",
                        this.checkUrl
                    ),
                clearInterval(
                    this._checkUrlInterval
                ),
                (History.started = !1);
            },
            route: function (
                route, callback
            ) {
                this.handlers.unshift(
                    {
                        route: route,
                        callback: callback,
                    }
                );
            },
            checkUrl: function (
                e
            ) {
                var current = this.getFragment(
                );
                if (
                    (current === this.fragment &&
            this.iframe &&
            (current = this.getFragment(
                this.getHash(
                    this.iframe
                )
            )),
                    current === this.fragment)
                )
                    return !1;
                this.iframe && this.navigate(
                    current
                ), this.loadUrl(
                );
            },
            loadUrl: function (
                fragment
            ) {
                return (
                    (fragment = this.fragment = this.getFragment(
                        fragment
                    )),
                    _.any(
                        this.handlers,
                        function (
                            handler
                        ) {
                            if (handler.route.test(
                                fragment
                            ))
                                return handler.callback(
                                    fragment
                                ), !0;
                        }
                    )
                );
            },
            navigate: function (
                fragment, options
            ) {
                if (!History.started) return !1;
                (options && !0 !== options) || (options = {
                    trigger: !!options,
                });
                var url = this.root + (fragment = this.getFragment(
                    fragment || ""
                ));
                if (
                    ((fragment = fragment.replace(
                        pathStripper,
                        ""
                    )),
                    this.fragment !== fragment)
                ) {
                    if (
                        ((this.fragment = fragment),
                        "" === fragment && "/" !== url && (url = url.slice(
                            0,
                            -1
                        )),
                        this._hasPushState)
                    )
                        this.history[options.replace ? "replaceState" : "pushState"](
                            {
                            },
                            document.title,
                            url,
                        );
                    else {
                        if (!this._wantsHashChange) return this.location.assign(
                            url
                        );
                        this._updateHash(
                            this.location,
                            fragment,
                            options.replace
                        ),
                        this.iframe &&
                fragment !== this.getFragment(
                    this.getHash(
                        this.iframe
                    )
                ) &&
                (options.replace || this.iframe.document.open(
                ).close(
                ),
                this._updateHash(
                    this.iframe.location,
                    fragment,
                    options.replace,
                ));
                    }
                    return options.trigger
                        ? this.loadUrl(
                            fragment
                        )
                        : void 0;
                }
            },
            _updateHash: function (
                location, fragment, replace
            ) {
                if (replace) {
                    var href = location.href.replace(
                        /(javascript:|#).*$/,
                        ""
                    );
                    location.replace(
                        href + "#" + fragment
                    );
                } else location.hash = "#" + fragment;
            },
        }
    ),
    (Backbone.history = new History(
    ));
    Model.extend = Collection.extend = Router.extend = View.extend = History.extend = function (
        protoProps,
        staticProps,
    ) {
        var child,
            parent = this;
        (child =
      protoProps && _.has(
          protoProps,
          "constructor"
      )
          ? protoProps.constructor
          : function (
          ) {
              return parent.apply(
                  this,
                  arguments
              );
          }),
        _.extend(
            child,
            parent,
            staticProps
        );
        var Surrogate = function (
        ) {
            this.constructor = child;
        };
        return (
            (Surrogate.prototype = parent.prototype),
            (child.prototype = new Surrogate(
            )),
            protoProps && _.extend(
                child.prototype,
                protoProps
            ),
            (child.__super__ = parent.prototype),
            child
        );
    };
    var urlError = function (
        ) {
            throw new Error(
                'A "url" property or function must be specified'
            );
        },
        wrapError = function (
            model, options
        ) {
            var error = options.error;
            options.error = function (
                resp
            ) {
                error && error(
                    model,
                    resp,
                    options
                ),
                model.trigger(
                    "error",
                    model,
                    resp,
                    options
                );
            };
        };
}.call(
    this
));
